﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading;

namespace Utils.Helper
{
    public class TempDirectory : IDisposable
    {

        private static readonly ConcurrentDictionary<string, TempDirectory> _tempDirectory = new ConcurrentDictionary<string, TempDirectory>();

        private static Timer timer;



        private static void TimerCallback(object obj)
        {
            var keys = _tempDirectory.Where(item => item.Value.ExpiryTime < DateTime.Now).Select(a => a.Key).ToArray();
            foreach (var item in keys)
            {
                _tempDirectory.TryRemove(item, out var temp);
                temp.Dispose();
            }
        }

        public static TempDirectory GetOrCreate(string key, int timeOut = 60 * 60)
        {
            return _tempDirectory.GetOrAdd(key, c => new TempDirectory(c)).Delay(timeOut);
        }

        public static string[] GetTemps()
        {
            return _tempDirectory.Keys.ToArray();
        }

        public static bool TryGetTemp(string key, out TempDirectory tempDirectory)
        {
            return _tempDirectory.TryGetValue(key, out tempDirectory);
        }
        /// <summary>
        /// 创建目录
        /// </summary>
        /// <param name="key"></param>
        /// <param name="tempDirectory"></param>
        /// <param name="timeOut">过期时间单位秒，默认 10 分钟</param>
        /// <returns></returns>
        public static bool TryCreate(string key, out TempDirectory tempDirectory, int timeOut = 60 * 10)
        {
            if (_tempDirectory.ContainsKey(key))
            {
                tempDirectory = null;
                return false;
            }
            _tempDirectory.TryAdd(key, tempDirectory = new TempDirectory(key).Delay(timeOut));
            return true;
        }

        public string TempPath { get; private set; }

        public DateTime ExpiryTime { get; private set; }



        public TempDirectory(string key)
        {
            TempPath = Path.Combine(Path.GetTempPath(), "dotnet_" + key.ToMD5Bit16());
            if (Directory.Exists(TempPath))
            {
                Directory.Delete(TempPath, true);
            }
            Directory.CreateDirectory(TempPath);
            timer ??= new Timer(TimerCallback, null, 1000, 1000);
        }

      

        public TempDirectory Delay(int timeOut)
        {
            ExpiryTime = DateTime.Now.AddSeconds(timeOut);
            return this;
        }
        public string[] GetFiles(bool withRoot = false)
        {
            var files = RecursiveGetFiles(TempPath);
            if (withRoot)
                return files.ToArray();
            int f = TempPath.Length + 1;
            return files.Select(a => a[f..]).ToArray();
        }

        private List<string> RecursiveGetFiles(string rootPath)
        {
            List<string> files = Directory.GetFiles(rootPath).ToList();
            string[] paths = Directory.GetDirectories(rootPath);
            foreach (string path in paths)
            {
                files.AddRange(RecursiveGetFiles(path));
            }
            return files;
        }
        public void Dispose()
        {
            if (Directory.Exists(TempPath))
            {
                // 删除临时文件
                Directory.Delete(TempPath, true);
            }
        }

        ~TempDirectory()
        {
            Dispose();
        }
    }
}
